package lumis.service.pagepersonalization.doui.dataprovider;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.portlet.PortletPreferences;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lumis.content.ContentManagerFactory;
import lumis.content.core.Content;
import lumis.content.core.ContentLocale;
import lumis.content.core.ContentVersion;
import lumis.doui.source.IDataProvider;
import lumis.doui.source.ISourceData;
import lumis.doui.source.TabularSource;
import lumis.doui.source.field.ITabularSourceField;
import lumis.portal.PortalContext;
import lumis.portal.PortalException;
import lumis.portal.PortalObjectNotFoundException;
import lumis.portal.PortalRequestParameters;
import lumis.portal.UnexpectedException;
import lumis.portal.authentication.SessionConfig;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.manager.ManagerFactoryInternal;
import lumis.portal.preferences.IPreferences;
import lumis.portal.servicecontainer.ServiceContainer;
import lumis.portal.servicecontainer.ServiceContainerRenderRequest;
import lumis.portal.servicecontainer.ServiceContainerRenderResponse;
import lumis.portal.serviceinterface.IServiceInterfaceRequest;
import lumis.portal.serviceinterfaceinstance.ServiceInterfaceInstanceConfig;
import lumis.service.pagepersonalization.PagePersonalizationUtil;
import lumis.service.pagepersonalization.bean.Widget;
import lumis.service.pagepersonalization.widgetmanipulationaction.PagePersonalizationManager;
import lumis.util.ITransaction;

/**
 * {@link IDataProvider} implementation that returns the widgets present in
 * current holder for current user.
 *
 * @version $Revision: 13246 $ $Date: 2011-07-14 17:08:26 -0300 (Thu, 14 Jul 2011) $
 * @since 6.0.0
 */
public class HolderServiceInterfaceDataProvider implements IDataProvider<TabularSource<ITabularSourceField>>
{
	private final String LUMIS_SERVICE_PAGEPERSONALIZATION_WIDGET_HOLDER = "lumis.service.pagepersonalization.widgetHolder";

	public void loadData(SessionConfig sessionConfig, TabularSource<ITabularSourceField> source, ITransaction transaction)
			throws PortalException
	{
		ServiceContainer serviceContainer = PortalContext.getServiceContainer();

		IServiceInterfaceRequest request = source.getDouiContext().getRequest();

		String[] widgets = null;
		
		// The user preferences have priority over the default configuration.
		// If there is user preferences, so the default configuration is ignored.
		// Otherwise, the default configuration is considered.
		
		// recover widgets preferences from the thread local.
		List<String> customWidgets = PagePersonalizationManager.getWidgetPreferences();
		if (!PagePersonalizationUtil.inEditMode(request))
		{
			if (customWidgets == null)
			{
				customWidgets = new ArrayList<String>();
				PagePersonalizationManager.setWidgetPreferences(customWidgets);
				// gets all widgets preferences among the holders existent on the page
				String pageId = source.getDouiContext().getRequest().getPageConfig().getId();
				Collection<String> serviceInterfaceInstanceIds = ManagerFactory.getServiceInterfaceInstanceManager().getIdsByPageId(sessionConfig, pageId, transaction);
				for (String string : serviceInterfaceInstanceIds)
				{
					ServiceInterfaceInstanceConfig serviceInterfaceInstanceConfig = ManagerFactoryInternal.getServiceInterfaceInstanceManager().get(sessionConfig, string, transaction);
					if (serviceInterfaceInstanceConfig.getServiceInterfaceId().equalsIgnoreCase(LUMIS_SERVICE_PAGEPERSONALIZATION_WIDGET_HOLDER))
					{
						IPreferences persistedPreferences = ManagerFactory.getPreferencesManager().getPreferences(sessionConfig, 
								string, IPreferences.TYPE_SERVICE_INTERFACE_INSTANCE);
						String[] values = persistedPreferences.getValues(PagePersonalizationUtil.WIDGETS_PREFERENCES_NAME, null);
						//if the values is different of null, then there is an user preference. 
						// This preference can be remove all widgets from the page.
						if (values != null)
						{
							// stores the holder id that have the custom preference.
							customWidgets.add(string);
						}
					}
				}
			}
			// gets the preferences for the current holder
			PortletPreferences pp = request.getPreferences();
			widgets = pp.getValues(PagePersonalizationUtil.WIDGETS_PREFERENCES_NAME, null);
			if (widgets == null && customWidgets.isEmpty())
			{
				widgets = PagePersonalizationUtil.getDefaultWidgets(sessionConfig, request.getServiceInterfaceInstanceId(),	request, transaction);
			}
		}
		else
		{
			widgets = PagePersonalizationUtil.getDefaultWidgets(sessionConfig, request.getServiceInterfaceInstanceId(),
					request, transaction);
		}

		Set<String> deletedWidgetContentIds = new HashSet<String>();
		if (widgets != null)
		{
			for (String widgetContentId : widgets)
			{
				if ("".equals(widgetContentId))
					continue;
	
				try
				{
					ContentManagerFactory.getContentManager().getContent(widgetContentId);
				}
				catch (PortalObjectNotFoundException e)
				{
					// this widget has been deleted
					deletedWidgetContentIds.add(widgetContentId);
					continue;
				}
	
				ContentVersion publishedContentVersion = null;
				try
				{
					publishedContentVersion = ContentManagerFactory.getContentManager().getPublishedContentVersion(widgetContentId, null);
				}
				catch (PortalObjectNotFoundException e){}
	
				Boolean untranslated = Boolean.FALSE;
	
				if (publishedContentVersion == null)
				{
					untranslated = Boolean.TRUE;
					Content content = ContentManagerFactory.getContentManager().getContent(widgetContentId);
	
					// try to find a content locale...
					for (ContentLocale contentLocale : content.getContentLocales())
					{
						if (contentLocale.getPublishedVersion() != null)
						{
							publishedContentVersion = contentLocale.getPublishedVersion();
							untranslated = !SessionConfig.getCurrentSessionConfig().getLocale().equals(contentLocale.getLocale());
							break;
						}
					}
				}
				else
				{
					untranslated = !SessionConfig.getCurrentSessionConfig().getLocale().equals(publishedContentVersion.getContentLocale().getLocale());
				}
	
				if (publishedContentVersion == null)
				{
					deletedWidgetContentIds.add(widgetContentId);
					continue;
				}
	
				if (!untranslated)
				{
					ISourceData row = source.getData().addRow();
		
					Widget widget = ManagerFactory.getEntityManager().find(Widget.class, publishedContentVersion.getItemId());
					row.put("id", widget.getId());
					row.put("contentId", widgetContentId);
					row.put("name", widget.getName());
					row.put("serviceInterfaceInstanceId", widget.getInterfaceInstanceId());
					{
						HttpServletRequest httpServletRequest = ((ServiceContainerRenderRequest) request).getServiceContainerHttpServletRequest()
								.getHttpServletRequest();
		
						PortalRequestParameters parameters = new PortalRequestParameters(SessionConfig.getCurrentSessionConfig(),
								httpServletRequest, null, transaction);
		
						ServiceContainerRenderRequest renderRequest = null;
						try
						{
							renderRequest = new ServiceContainerRenderRequest(SessionConfig.getCurrentSessionConfig(),
									parameters, httpServletRequest);
						}
						catch (Exception e)
						{
							throw new PortalException(e.getMessage(), e);
						}
		
						ServiceContainerRenderRequest originalRenderRequest = (ServiceContainerRenderRequest) request;
		
						renderRequest.setPrinting(originalRenderRequest.isPrinting());
						renderRequest.setSessionConfig(SessionConfig.getCurrentSessionConfig());
						renderRequest.setPageWebResource(originalRenderRequest.getPageWebResource());
						renderRequest.setMode(originalRenderRequest.getMode());
		
						renderRequest.setPreview(originalRenderRequest.isPreview());
						renderRequest.setPageCacheId(originalRenderRequest.getPageCacheId());
		
						renderRequest.setServiceInterfaceInstanceId(widget.getInterfaceInstanceId());
						renderRequest.setCallerServiceInterfaceInstanceId(originalRenderRequest.getCallerServiceInterfaceInstanceId());
		
						ServiceContainerRenderResponse renderResponse = new ServiceContainerRenderResponse(renderRequest,
								(HttpServletResponse) source.getDouiContext().getResponse());
		
						renderResponse.setPageWebResource(originalRenderRequest.getPageWebResource());
						renderResponse.setServiceInterfaceInstanceId(widget.getInterfaceInstanceId());
		
						row.put("renderedContent", serviceContainer
								.renderServiceInterfaceInstance(renderRequest, renderResponse, transaction));
					}
				}
			}
		}
		if (!deletedWidgetContentIds.isEmpty())
		{
			IPreferences pp = ManagerFactory.getPreferencesManager().getPreferences(sessionConfig,
					request.getServiceInterfaceInstanceConfig().getId(), IPreferences.TYPE_SERVICE_INTERFACE_INSTANCE);
			widgets = pp.getValues(PagePersonalizationUtil.WIDGETS_PREFERENCES_NAME, null);
			if (widgets != null)
			{
				List<String> currentWidgets = Arrays.asList(widgets);
				List<String> newWidgets = new ArrayList<String>();
				for (String widget : currentWidgets)
					if (!deletedWidgetContentIds.contains(widget))
						newWidgets.add(widget);

				widgets = newWidgets.toArray(new String[newWidgets.size()]);

				try
				{
					pp.setValues(PagePersonalizationUtil.WIDGETS_PREFERENCES_NAME, widgets);
					pp.store();
				}
				catch (Exception e)
				{
					throw new UnexpectedException(e);
				}
			}
		}
	}
}
